package com.bac.rentmap.ad.flat.crawler.realtby;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.CompactXmlSerializer;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.bac.rentmap.ad.crawler.AdCrawler;
import com.bac.rentmap.ad.crawler.Context;
import com.bac.rentmap.ad.crawler.CrawledAd;
import com.bac.rentmap.ad.flat.LocalAddress;
import com.bac.rentmap.ad.flat.crawler.FlatCrawledAd;

public class SaxRealtByAdCrawler implements AdCrawler<CrawledAd> {
    private static final Logger log = Logger
            .getLogger(RealtBySteppedAdCrawler.class.getName());

    private String url = "http://realt.by/rent/flat-for-long/show/table/page/1/print.html";

    public List<CrawledAd> crawl(Context context) throws IOException {
        Reader inputStreamReader = new InputStreamReader(getInputStream());
        BufferedReader reader = new BufferedReader(inputStreamReader);
        CleanerProperties cleanerProperties = new CleanerProperties();
        cleanerProperties.setUseCdataForScriptAndStyle(false);
        cleanerProperties.setAdvancedXmlEscape(true);

        HtmlCleaner htmlCleaner = new HtmlCleaner(cleanerProperties);
        TagNode rootNode = htmlCleaner.clean(reader);
        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
        new CompactXmlSerializer(htmlCleaner.getProperties()).writeXmlToStream(
                rootNode, arrayOutputStream);
        DocumentBuilderFactory domFactory = DocumentBuilderFactory
                .newInstance();
        domFactory.setNamespaceAware(false);
        DocumentBuilder builder;
        try {
            builder = domFactory.newDocumentBuilder();
            Document doc = builder.parse(new ByteArrayInputStream(
                    arrayOutputStream.toByteArray()));
            XPath xpath = XPathFactory.newInstance().newXPath();
            XPathExpression expr = xpath
                    .compile("//*/tr[count(td) > 1 and position() > 3]");
            Object result = expr.evaluate(doc, XPathConstants.NODESET);
            NodeList nodes = (NodeList) result;
            log.info("" + nodes.getLength());
            List<CrawledAd> res = new ArrayList<CrawledAd>();
            for (int i = 0; i < nodes.getLength(); i++) {
                res.add(parseCrawledAd(nodes.item(i)));
            }
            return res;
        } catch (ParserConfigurationException e1) {
            e1.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        // try {
        // Object[] objects = rootNode
        // .evaluateXPath("//body/div/table/tbody/tr[position() > 3]");
        // System.out.println("aaa" + objects.length);
        // List<CrawledAd> res = new ArrayList<CrawledAd>();
        // for (Object object : objects) {
        // TagNode tagNode = (TagNode) object;
        // System.out.println("hello" + object.getClass() + " "
        // + tagNode.getText());
        // try {
        // res.add(parseCrawledAd(tagNode));
        // } catch (IllegalArgumentException e) {
        // }
        // }
        // return res;
        // } catch (XPatherException e) {
        // throw new RuntimeException("Invalid XPATH", e);
        // } finally {
        // reader.close();
        // }
        return null;
    }

    private CrawledAd parseCrawledAd(Node node) {
        log.info(node.toString());
        FlatCrawledAd res = new FlatCrawledAd();
        NodeList children = node.getChildNodes();
        res.setLocalAddress(new LocalAddress(null, children.item(3)
                .getTextContent(), null));
        return res;
    }

    // private String getValue(Node node, int i)
    // throws XPatherException {
    // node.getChildNodes().item(i)
    // Object[] xpathValue = tagNode.evaluateXPath(xpath);
    // if (xpathValue.length != 1) {
    // throw new IllegalArgumentException("Can't evaluate XPATH " + xpath
    // + " for " + tagNode.getText() + ", length is "
    // + xpathValue.length);
    // }
    // return ((TagNode) xpathValue[0]).getText().toString();
    // }

    protected InputStream getInputStream() throws IOException {
        return new URL(url).openStream();
    }
}
